home *** CD-ROM | disk | FTP | other *** search
/ FM Towns: Free Software Collection 8 / FM Towns Free Software Collection 8.iso / t_os / wink24h / src / buff.c < prev    next >
Text File  |  1994-06-01  |  14KB  |  691 lines

  1. /*
  2.     buffer I/O
  3. */
  4. #include    <stdio.h>
  5. #include    <stdlib.h>
  6. #include    <string.h>
  7.  
  8. #define TRUE    1
  9. #define FALSE   0
  10. #define ERR     (-1)
  11.  
  12. #define PTR(p)  (unsigned int)(p)
  13. #define unlink  remove
  14. #define MAX_BUF (16384-24)
  15.  
  16. #define HEAD_SIZ    (sizeof(BUF_PTR)-MAX_BUF)
  17. #define SEEK_POS(n) ((long)(n)*sizeof(BUF_PTR))
  18.  
  19. #define WRITE_ERR   1
  20. #define READ_ERR    2
  21.  
  22. typedef struct _BP {
  23.     struct _BP  *next;
  24.     int         alno;
  25.     int         left;
  26.     int         right;
  27.     int         len;
  28.     int        lfc;
  29.     char        buf[MAX_BUF];
  30. } BUF_PTR;
  31.  
  32. typedef struct _EP {
  33.     struct _EP  *next;
  34.     int         actno;
  35.     int         actpos;
  36.     long        pos;
  37.     long     line;
  38. } EDT_PTR;
  39.  
  40. extern void    wrtstr();
  41. extern int    Input();
  42. extern char     *Tmp_device_name;
  43.  
  44. EDT_PTR *edt_top=NULL;
  45.  
  46. static EDT_PTR    *undo_edt=NULL;
  47. static long    undo_sz=0L;
  48. static FILE    *tfp=NULL;
  49. static int    free_no=ERR;
  50. static BUF_PTR    *top_ptr=NULL;
  51. static char    TMPFILE[80];
  52.  
  53. unsigned long int Freemem()
  54. {
  55.     int     mx;
  56.     unsigned long int sz,fm;
  57.     char    *dmy[128];
  58.  
  59.     for ( sz = 0x10000,fm = mx = 0 ; mx < 128 ; mx++ ) {
  60.     while ( (dmy[mx] = malloc(sz)) == NULL ) {
  61.         if ( (sz /= 2) < 0x1000 )
  62.         break;
  63.     }
  64.     if ( dmy[mx] == NULL )
  65.         break;
  66.     fm += sz;
  67.     }
  68.     while ( mx > 0 )
  69.     free(dmy[--mx]);
  70.     return fm;
  71. }
  72. int     Bfp_init()
  73. {
  74.     int     i;
  75.     BUF_PTR *bp;
  76.     char    *p;
  77.     unsigned long int l;
  78.  
  79.     l = Freemem() / 2;
  80.     i = l / sizeof(BUF_PTR);
  81.  
  82.     if ( (bp = (BUF_PTR *)malloc(sizeof(BUF_PTR)*i)) == NULL )
  83.     return ERR;
  84.  
  85.     top_ptr = bp;
  86.     for ( i-- ; i > 0 ; i-- ) {
  87.         bp->next = bp + 1;
  88.         bp->alno = ERR;
  89.         bp++;
  90.     }
  91.     bp->next = NULL;
  92.     bp->alno = ERR;
  93.  
  94.     if ( (p = Tmp_device_name) != NULL ||
  95.          (p = getenv("TMP")) != NULL )
  96.     sprintf(TMPFILE,"%s\\",p);
  97.     else
  98.         TMPFILE[0] = '\0';
  99.     strcat(TMPFILE,"WINK.TMP");
  100.  
  101.     New_link();
  102.     undo_edt = edt_top;
  103.     New_link();
  104.  
  105.     return FALSE;
  106. }
  107. void    Bfp_end()
  108. {
  109.     if ( tfp != NULL ) {
  110.     fclose(tfp);
  111.     unlink(TMPFILE);
  112.     }
  113. }
  114. static void    retry(no)
  115. int    no;
  116. {
  117.     static char *msg[]={
  118.     "Save Temp Seek Error        ",
  119.     "Save Temp Write Header Error",
  120.     "Save Temp Write Buffer Error",
  121.     "Load Temp Seek Error        ",
  122.     "Load Temp Read Header Error ",
  123.     "Save Temp Read Buffer Error ",
  124.     "New Temp File Can't open    ",
  125.     "New Temp Write Error        ",
  126.     "Temp File Can't open        "
  127.     };
  128.     int     i;
  129.     FILE    *fp;
  130.     char    tmp[80];
  131.     char    buf[512];
  132.  
  133. RETRY:
  134.     do {
  135.     wrtstr(msg[no],30,1,0x12);
  136.     tmp[0] = '\0';
  137.         while ( (short int)Input(tmp,"テンポラリドライブ名 ") != FALSE );
  138.     if ( strcmp(tmp,"EXIT") == 0 )
  139.         exit(10);
  140.     strcat(tmp,"\\WINK.TMP");
  141.     wrtstr("                            ",30,1,0x1F);
  142.     no = 6;
  143.     } while ( (fp = fopen(tmp,"w+b")) == NULL );
  144.  
  145.     if ( tfp != NULL ) {
  146.     fseek(tfp,0L,SEEK_SET);
  147.     while ( (i = fread(buf,1,512,tfp)) > 0 )
  148.         fwrite(buf,1,i,fp);
  149.     }
  150.  
  151.     if ( ferror(fp) ) {
  152.     fclose(fp);
  153.     unlink(tmp);
  154.     no = 7;
  155.     goto RETRY;
  156.     }
  157.  
  158.     if ( tfp != NULL ) {
  159.     fclose(tfp);
  160.     unlink(TMPFILE);
  161.     }
  162.  
  163.     tfp = fp;
  164.     strcpy(TMPFILE,tmp);
  165. }
  166. static void    save_buf(bp)
  167. register BUF_PTR *bp;
  168. {
  169.     if ( tfp == NULL && (tfp = fopen(TMPFILE,"w+b")) == NULL ) {
  170.     retry(8);
  171.     goto RETRY;
  172.     }
  173. RETRY:
  174.     if ( fseek(tfp,SEEK_POS(bp->alno),SEEK_SET) ) {
  175.     retry(0);
  176.     goto RETRY;
  177.     }
  178.     if ( fwrite((char *)bp,HEAD_SIZ,1,tfp) < 1 ) {
  179.     retry(1);
  180.     goto RETRY;
  181.     }
  182.     if ( bp->len > 0 && fwrite(bp->buf,1,bp->len,tfp) < bp->len ) {
  183.     retry(2);
  184.     goto RETRY;
  185.     }
  186. }
  187. static void    load_buf(no,bp)
  188. int     no;
  189. register BUF_PTR *bp;
  190. {
  191.     BUF_PTR *tp;
  192.  
  193.     if ( tfp == NULL && (tfp = fopen(TMPFILE,"w+b")) == NULL ) {
  194.     retry(8);
  195.     goto RETRY;
  196.     }
  197. RETRY:
  198.     if ( fseek(tfp,SEEK_POS(no),SEEK_SET) ) {
  199.     retry(3);
  200.     goto RETRY;
  201.     }
  202.     tp = bp->next;
  203.     if ( fread((char *)bp,HEAD_SIZ,1,tfp) < 1 ) {
  204.     bp->next = tp;
  205.     retry(4);
  206.     goto RETRY;
  207.     }
  208.     bp->next = tp;
  209.     if ( bp->len > 0 && fread(bp->buf,1,bp->len,tfp) < bp->len ) {
  210.     retry(5);
  211.     goto RETRY;
  212.     }
  213. }
  214. static BUF_PTR *get_buf(no)
  215. int     no;
  216. {
  217.     BUF_PTR *tp;
  218.     register BUF_PTR *bp;
  219.  
  220.     bp = top_ptr;
  221.     while ( bp->alno != no ) {
  222.     if ( bp->next == NULL ) {
  223.             if ( bp->alno != ERR )
  224.                 save_buf(bp);
  225.             if ( no != ERR )
  226.                 load_buf(no,bp);
  227.             break;
  228.     }
  229.     tp = bp;
  230.     bp = bp->next;
  231.     }
  232.     if ( bp != top_ptr ) {
  233.     tp->next = bp->next;
  234.     bp->next = top_ptr;
  235.     top_ptr = bp;
  236.     }
  237.     return bp;
  238. }
  239. static int     xalloc()
  240. {
  241.     static int   alno=0;
  242.     register BUF_PTR *bp;
  243.  
  244.     if ( free_no != ERR ) {
  245.         bp = get_buf(free_no);
  246.         free_no = bp->left;
  247.     } else {
  248.     bp = get_buf(ERR);
  249.     bp->alno = alno++;
  250.     }
  251.     bp->left = bp->right = ERR;
  252.     bp->len = 0;
  253.     bp->lfc = ERR;
  254.     return bp->alno;
  255. }
  256. static void    xfree(no)
  257. int     no;
  258. {
  259.     register BUF_PTR *bp;
  260.  
  261.     bp = get_buf(no);
  262.     bp->left = free_no;
  263.     free_no = no;
  264.     bp->len = 0;
  265. }
  266. static int     link_buf(no)
  267. int     no;
  268. {
  269.     int    new;
  270.     BUF_PTR *tp;
  271.     BUF_PTR *bp;
  272.  
  273.     new = xalloc();
  274.     tp = get_buf(no);                   /* 1 */
  275.     bp = get_buf(new);                  /* 2 */
  276.  
  277.     bp->left = no;
  278.     bp->right = tp->right;
  279.     tp->right = new;
  280.  
  281.     if ( bp->right != ERR ) {
  282.         tp = get_buf(bp->right);        /* 3 */
  283.         tp->left = new;
  284.     }
  285.     return new;
  286. }
  287. static void    del_buf(no)
  288. int     no;
  289. {
  290.     BUF_PTR *tp;
  291.     BUF_PTR *bp;
  292.  
  293.     bp = get_buf(no);
  294.     if ( bp->left != ERR ) {
  295.         tp = get_buf(bp->left);
  296.         tp->right = bp->right;
  297.     }
  298.     if ( bp->right != ERR ) {
  299.         tp = get_buf(bp->right);
  300.         tp->left = bp->left;
  301.     }
  302.     xfree(no);
  303. }
  304. static int     line_count(bp)
  305. register BUF_PTR *bp;
  306. {
  307.     int     i,n;
  308.     register char *p;
  309.  
  310.     if ( bp->lfc == ERR ) {
  311.         p = bp->buf;
  312.         n = 0;
  313.         for ( i = bp->len ; i > 0 ; i-- ) {
  314.             if ( *(p++) == '\n' )
  315.                 n++;
  316.         }
  317.         bp->lfc = n;
  318.     }
  319.     return bp->lfc;
  320. }
  321. static char    *chk_ptr(ep,pos)
  322. register EDT_PTR *ep;
  323. long    pos;
  324. {
  325.     BUF_PTR *bp;
  326.  
  327.     bp = get_buf(ep->actno);
  328.     while ( (ep->pos + bp->len) < pos ) {
  329.         if ( bp->right == ERR )
  330.             return &(bp->buf[bp->len]);
  331.         ep->actno = bp->right;
  332.         ep->pos += bp->len;
  333.         ep->line += line_count(bp);
  334.         bp = get_buf(ep->actno);
  335.     }
  336.     while ( ep->pos > pos ) {
  337.     if ( bp->left == ERR )
  338.         return bp->buf;
  339.     ep->actno = bp->left;
  340.     bp = get_buf(ep->actno);
  341.     ep->pos -= bp->len;
  342.     ep->line -= line_count(bp);
  343.     }
  344.     return &(bp->buf[(int)(pos - ep->pos)]);
  345. }
  346. static long    get_line(ep,line)
  347. register EDT_PTR *ep;
  348. int    *line;
  349. {
  350.     int     t;
  351.     int     n,i;
  352.     char    *p;
  353.     BUF_PTR *bp;
  354.  
  355.     bp = get_buf(ep->actno);
  356.     while ( (ep->line + line_count(bp)) < *line ) {
  357.         if ( bp->right == ERR ) {
  358.         *line = ep->line + line_count(bp);
  359.         break;
  360.     }
  361.         ep->actno = bp->right;
  362.         ep->pos += bp->len;
  363.         ep->line += line_count(bp);
  364.         bp = get_buf(ep->actno);
  365.     }
  366.     while ( ep->line >= *line ) {
  367.     if ( bp->left == ERR ) {
  368.         *line = ep->line;
  369.         break;
  370.     }
  371.     ep->actno = bp->left;
  372.     bp = get_buf(ep->actno);
  373.     ep->pos -= bp->len;
  374.     ep->line -= line_count(bp);
  375.     }
  376.  
  377.     p = bp->buf;
  378.     t = n = *line - ep->line;
  379.     i = 0;
  380.     while ( n > 0 && i < bp->len ) {
  381.     if ( *(p++) == '\n' )
  382.         n--;
  383.     i++;
  384.     }
  385.     *line -= n;
  386.  
  387.     return (ep->pos + (long)i);
  388. }
  389. char    *Cnv_ptr(pos)
  390. long    pos;
  391. {
  392.     register EDT_PTR *ep;
  393.     register BUF_PTR *bp;
  394.  
  395.     ep = edt_top;
  396.     bp = get_buf(ep->actno);
  397.     while ( (ep->pos + bp->len) <= pos ) {
  398.         if ( bp->right == ERR )
  399.             return &(bp->buf[bp->len]);
  400.         ep->actno = bp->right;
  401.         ep->pos += bp->len;
  402.         ep->line += line_count(bp);
  403.         bp = get_buf(ep->actno);
  404.     }
  405.     while ( ep->pos > pos ) {
  406.     if ( bp->left == ERR )
  407.         return bp->buf;
  408.     ep->actno = bp->left;
  409.     bp = get_buf(ep->actno);
  410.     ep->pos -= bp->len;
  411.     ep->line -= line_count(bp);
  412.     }
  413.     return &(bp->buf[(int)(pos - ep->pos)]);
  414. }
  415. static int     ins_str(ep,pos,str,n)
  416. EDT_PTR *ep;
  417. long    pos;
  418. char    *str;
  419. int     n;
  420. {
  421.     int     tn,i,len;
  422.     BUF_PTR *tp;
  423.     BUF_PTR *bp;
  424.     char    *p;
  425.     static char tmp[MAX_BUF];
  426.  
  427.     p = chk_ptr(ep,pos);
  428.     bp = get_buf(ep->actno);
  429.     if ( (tn = &bp->buf[bp->len] - p) > 0 ) {
  430.     memcpy(tmp,p,tn);
  431.     bp->len -= tn;
  432.     }
  433.  
  434.     len = n + tn;
  435.     for ( ; len > 0 ; ) {
  436.     if ( bp->len >= MAX_BUF ) {
  437.         bp = get_buf(link_buf(bp->alno));
  438.         p = bp->buf;
  439.         }
  440.  
  441.     if ( n == 0 ) {
  442.         n = tn;
  443.         str = tmp;
  444.         }
  445.  
  446.     i = PTR(&(bp->buf[MAX_BUF])) - PTR(p);
  447.     if ( i > n ) i = n;
  448.  
  449.     memcpy(p,str,i);
  450.     p += i;
  451.     str += i;
  452.     n -= i;
  453.     len -= i;
  454.     bp->len += i;
  455.     bp->lfc = ERR;
  456.     }
  457.  
  458.     if ( bp->right != ERR ) {
  459.         tp = get_buf(bp->right);
  460.     if ( (bp->len + tp->len) < MAX_BUF ) {
  461.             memcpy(&bp->buf[bp->len],tp->buf,tp->len);
  462.             bp->len += tp->len;
  463.             bp->lfc = ERR;
  464.             del_buf(bp->right);
  465.         }
  466.     }
  467.  
  468.     return FALSE;
  469. }
  470. static int     del_str(ep,pos,len)
  471. EDT_PTR *ep;
  472. long    pos;
  473. int     len;
  474. {
  475.     int     i,n;
  476.     BUF_PTR *tp;
  477.     BUF_PTR *bp;
  478.     char    *p;
  479.  
  480.     p = chk_ptr(ep,pos);
  481.     bp = get_buf(ep->actno);
  482.  
  483.     for ( ; len > 0 ; ) {
  484.     n = &bp->buf[bp->len] - p;
  485.     if ( n <= len ) {
  486.             bp->len -= n;
  487.             len -= n;
  488.     } else {
  489.         memcpy(p,p+len,n-(int)len);
  490.         bp->len -= len;
  491.         len = 0;
  492.         }
  493.     bp->lfc = ERR;
  494.     if ( bp->len == 0 && bp->right != ERR ) {
  495.             if ( (i = bp->alno) == ep->actno )
  496.                 ep->actno = bp->right;
  497.             bp = get_buf(bp->right);
  498.             del_buf(i);
  499.     } else if ( len > 0 && bp->right != ERR ) {
  500.         bp = get_buf(bp->right);
  501.         } else
  502.         break;
  503.         p = bp->buf;
  504.     }
  505.  
  506.     if ( bp->right != ERR ) {
  507.     tp = get_buf(bp->right);
  508.     if ( (bp->len + tp->len) < MAX_BUF ) {
  509.         memcpy(&bp->buf[bp->len],tp->buf,tp->len);
  510.         bp->len += tp->len;
  511.         bp->lfc = ERR;
  512.         del_buf(bp->right);
  513.         }
  514.     }
  515.  
  516.     return FALSE;
  517. }
  518. static int     cut_str(ep,pos,str,n)
  519. EDT_PTR *ep;
  520. long    pos;
  521. char    *str;
  522. int     n;
  523. {
  524.     int     i,len;
  525.     BUF_PTR *bp;
  526.     char    *p;
  527.  
  528.     p = chk_ptr(ep,pos);
  529.     bp = get_buf(ep->actno);
  530.  
  531.     for ( len = 0 ; n > 0 ; ) {
  532.         i = &bp->buf[bp->len] - p;
  533.         if ( i > n ) i = n;
  534.         memcpy(str,p,i);
  535.         str += i;
  536.         n -= i;
  537.         len += i;
  538.         if ( n > 0 ) {
  539.         if ( bp->right == ERR )
  540.         break;
  541.         bp = get_buf(bp->right);
  542.             p = bp->buf;
  543.         }
  544.     }
  545.  
  546.     return len;
  547. }
  548. long    Line_ptr(n)
  549. int    *n;
  550. {
  551.     return get_line(edt_top,n);
  552. }
  553. void    Ins_buf(ptr,sz,str)
  554. long    ptr;
  555. int     sz;
  556. char    *str;
  557. {
  558.     ins_str(edt_top,ptr,str,sz);
  559. }
  560. void    Del_buf(ptr,sz)
  561. long    ptr;
  562. long    sz;
  563. {
  564.     int     n;
  565.  
  566.     while ( sz > 0 ) {
  567.     n = (sz > 16384 ? 16384:sz);
  568.     del_str(edt_top,ptr,n);
  569.     sz -= n;
  570.     }
  571. }
  572. void    Cut_buf(str,sz,ptr)
  573. char    *str;
  574. int     sz;
  575. long    ptr;
  576. {
  577.     cut_str(edt_top,ptr,str,sz);
  578. }
  579. int    New_link()
  580. {
  581.     EDT_PTR *ep;
  582.  
  583.     if ( (ep = (EDT_PTR *)malloc(sizeof(EDT_PTR))) == NULL )
  584.         return ERR;
  585.  
  586.     ep->next = edt_top;
  587.     edt_top = ep;
  588.  
  589.     ep->actno = xalloc();
  590.     ep->pos = 0L;
  591.     ep->line = 0;
  592.  
  593.     return FALSE;
  594. }
  595. void    Kill_link(ep)
  596. EDT_PTR    *ep;
  597. {
  598.     int     no;
  599.     BUF_PTR *bp;
  600.  
  601.     no = ep->actno;
  602.     for ( ; ; ) {
  603.     bp = get_buf(no);
  604.     if ( bp->left == ERR )
  605.         break;
  606.     no = bp->left;
  607.     }
  608.     while ( no != ERR ) {
  609.     bp = get_buf(no);
  610.     no = bp->right;
  611.     xfree(bp->alno);
  612.     }
  613.     free(ep);
  614. }
  615. long    Nxt_line(pos)
  616. long    pos;
  617. {
  618.     int     i;
  619.     char    *p;
  620.     register EDT_PTR *ep;
  621.     register BUF_PTR *bp;
  622.     extern long btm_ptr;
  623.  
  624.     p = Cnv_ptr(pos);
  625.     ep = edt_top;
  626.     bp = get_buf(ep->actno);
  627.     do {
  628.         while ( p >= &(bp->buf[bp->len]) ) {
  629.             if ( bp->right == ERR ) {
  630.         p = &(bp->buf[bp->len]);
  631.         goto ENDOF;
  632.         }
  633.         i = PTR(p) - PTR(&(bp->buf[bp->len]));
  634.             ep->actno = bp->right;
  635.             ep->pos += bp->len;
  636.             ep->line += line_count(bp);
  637.             bp = get_buf(ep->actno);
  638.         p = &(bp->buf[i]);
  639.         }
  640.     } while ( *(p++) != '\n' );
  641. ENDOF:
  642.     pos = (ep->pos + (long)(PTR(p) - PTR(bp->buf)));
  643.     return (pos > btm_ptr ? btm_ptr : pos);
  644. }
  645. void    Undo_put(ptr,sz)
  646. long    ptr,sz;
  647. {
  648.     int     n;
  649.     char    tmp[256];
  650.  
  651.     while ( undo_sz > 0 ) {
  652.     n = (undo_sz > 16384 ? 16384:undo_sz);
  653.     del_str(undo_edt,0L,n);
  654.     undo_sz -= n;
  655.     }
  656.     while ( sz > 0 ) {
  657.     n = (sz > 256 ? 256:sz);
  658.     cut_str(edt_top,ptr,tmp,n);
  659.     ins_str(undo_edt,undo_sz,tmp,n);
  660.     sz -= n;
  661.     ptr += n;
  662.     undo_sz += n;
  663.     }
  664. }
  665. long    Undo_get(ptr)
  666. long    ptr;
  667. {
  668.     int     n;
  669.     long    sz,pos;
  670.     char    tmp[256];
  671.  
  672.     sz = undo_sz;
  673.     pos = 0L;
  674.     while ( sz > 0 ) {
  675.     n = (sz > 256 ? 256:sz);
  676.     cut_str(undo_edt,pos,tmp,n);
  677.     ins_str(edt_top,ptr,tmp,n);
  678.     sz -= n;
  679.     pos += n;
  680.     ptr += n;
  681.     }
  682.     return undo_sz;
  683. }
  684. int    Undo_cpy(buf,sz,pos)
  685. char    *buf;
  686. int    sz;
  687. long    pos;
  688. {
  689.     return cut_str(undo_edt,pos,buf,sz);
  690. }
  691.